﻿using DNFImagePacks2Manager.Helpers;
using DNFImagePacks2Manager.Models;
using Microsoft.UI;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

namespace DNFImagePacks2Manager.Pages
{
    public sealed partial class ProcessSaveBKPage : Page
    {
        private readonly DispatcherQueue _dispatcherQueue;
        public ProcessSaveBKPage()
        {
            InitializeComponent();
            _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
        }

        public async Task<Dictionary<string, BKItemHash>> GenerateFileHashDic(bool addWhole)
        {

            string storagePath = LocalStorageHelper.GetBKStoragePath();
            Dictionary<string, BKItemHash> hashFileDic = [];

            try
            {

                await DispatchToUI(() =>
                {
                    AddLog($"正在为单品BK文件生成哈希表", "blue");
                });

                var singleList = BKListHelper.GetSingleBKItems();
                foreach (var singleItem in singleList)
                {
                    string singleName = singleItem.Name;
                    string singleFile = singleItem.BKFile;
                    if (!File.Exists(singleFile))
                    {
                        continue;
                    }
                    try
                    {
                        await DispatchToUI(() =>
                        {
                            AddLog($"正在为单品文件生成哈希值: {singleName}", "blue");
                        });
                        string hash = await HashHelper.GetFileSHA256(singleFile);
                        if (hashFileDic.ContainsKey(hash))
                        {
                            await DispatchToUI(() =>
                            {
                                AddLog($"哈希值重复，跳过", "blue");
                            });
                        }
                        else
                        {
                            hashFileDic.Add(hash, new BKItemHash(singleName, BKItemHash.GetRelativeFile(singleFile, storagePath, out bool isRelative), false));
                            await DispatchToUI(() =>
                            {
                                AddLog($"哈希值生成成功: {hash}", "green");
                            });
                        }
                    }
                    catch (Exception ex) {
                        await DispatchToUI(() =>
                        {
                            AddLog($"哈希值生成失败: {ex.Message}", "red");
                        });
                    }
                }

                if (addWhole)
                {

                    await DispatchToUI(() =>
                    {
                        AddLog($"正在为套装BK文件生成哈希表", "blue");
                    });

                    var wholeList = BKListHelper.GetWholeBKItems();
                    foreach (var wholeItem in wholeList)
                    {
                        string wholeName = wholeItem.Name;
                        string wholeFolder = wholeItem.BKFolder;
                        string[] files = Directory.GetFiles(wholeFolder, "*.*", SearchOption.AllDirectories);
                        foreach (string file in files)
                        {
                            try
                            {
                                await DispatchToUI(() =>
                                {
                                    AddLog($"正在为套装文件生成哈希值: {file}", "blue");
                                });
                                string hash = await HashHelper.GetFileSHA256(file);
                                if (hashFileDic.ContainsKey(hash))
                                {
                                    await DispatchToUI(() =>
                                    {
                                        AddLog($"哈希值重复，跳过", "blue");
                                    });
                                }
                                else
                                {
                                    hashFileDic.Add(hash, new BKItemHash(wholeName, BKItemHash.GetRelativeFile(file, storagePath, out bool isRelative), true));
                                    await DispatchToUI(() =>
                                    {
                                        AddLog($"哈希值生成成功: {hash}", "green");
                                    });
                                }
                            }
                            catch (COMException ex)
                            {
                                await DispatchToUI(() =>
                                {
                                    AddLog($"COM 异常 - 错误代码: 0x{ex.ErrorCode:X8}, 错误信息: {ex.Message}", "red");
                                    AddLog($"调用栈: {ex.StackTrace}", "red");
                                });
                            }
                            catch (Exception ex)
                            {
                                await DispatchToUI(() =>
                                {
                                    AddLog($"哈希值生成失败: {ex.Message}", "red");
                                });
                            }
                        }
                    }
                }
                else
                {
                    await DispatchToUI(() =>
                    {
                        AddLog($"未设置检索套装文件，已跳过", "blue");
                    });
                }

                await DispatchToUI(() =>
                {
                    AddLog($"哈希表生成完成，数量: {hashFileDic.Count}", "blue");
                });
            }
            catch (Exception ex){
                await DispatchToUI(() => AddLog($"生成哈希表时发生错误: {ex.Message}", "red"));
            }
            return hashFileDic;
        }

        public async Task StartExportTask(string saveName, bool addWhole, bool isCustom)
        {

            Dictionary<string, BKItemHash> hashFileDic = await GenerateFileHashDic(addWhole);

            if (hashFileDic.Count == 0) {
                await DispatchToUI(() =>
                {
                    TitleTextBlock.Text = "缓存补丁哈希表生成失败";
                    AddLog($"缓存补丁哈希表生成失败", "red");
                    DialogHelper.ShowErrorMessage(this, $"缓存补丁哈希表生成失败");
                });
                return;
            }

            string bkFolder = LocalStorageHelper.GetBKOfficialPath();
            var categoryDic = BKPathHelper.CategoryDirectory;
            int total = categoryDic.Count;

            await DispatchToUI(() =>
            {
                AddLog($"正在检索已安装文件对应的缓存", "blue");
            });

            Dictionary<string, BKItemHash> customDic = [];

            int current = 0;
            foreach (var categoryItem in categoryDic)
            {
                try
                {
                    current++;
                    string path = categoryItem.Key;
                    string name = categoryItem.Value;
                    await DispatchToUI(() =>
                    {
                        UpdateProcess(name, current, total);
                        AddLog($"正在为文件生成哈希值并对比: {name}", "blue");
                    });
                    string file = Path.Combine(bkFolder, path);
                    string hash = await HashHelper.GetFileSHA256(file);
                    await DispatchToUI(() =>
                    {
                        AddLog($"哈希值生成成功: {hash}", "green");
                    });
                    if (hashFileDic.ContainsKey(hash)) {
                        BKItemHash hashItem = hashFileDic[hash];
                        await DispatchToUI(() =>
                        {
                            AddLog($"哈希值比对成功: {hashItem.name}", "green");
                        });
                        customDic.Add(path, hashItem);
                    }
                    else
                    {
                        await DispatchToUI(() =>
                        {
                            AddLog($"哈希值对比失败，跳过", "green");
                        });
                    }
                }
                catch (COMException ex)
                {
                    await DispatchToUI(() =>
                    {
                        AddLog($"COM 异常 - 错误代码: 0x{ex.ErrorCode:X8}, 错误信息: {ex.Message}", "red");
                        AddLog($"调用栈: {ex.StackTrace}", "red");
                    });
                }
                catch (Exception ex)
                {
                    await DispatchToUI(() =>
                    {
                        AddLog($"哈希值生成失败: {ex.Message}", "red");
                    });
                }
            }

            if(customDic.Count == 0)
            {
                await DispatchToUI(() =>
                {
                    TitleTextBlock.Text = "映射补丁文件失败";
                    AddLog($"未检测到缓存文件中存在已安装补丁", "red");
                    DialogHelper.ShowErrorMessage(this, $"未检测到缓存文件中存在已安装补丁");
                });
                return;
            }

            if (isCustom)
            {

                await DispatchToUI(() =>
                {
                    AddLog($"正在保存为配置文件", "blue");
                });

                try
                {
                    string saveFile = Path.Combine(BKHelper.GetCustomFolder(), saveName + ".json");

                    var settings = new JsonSerializerSettings
                    {
                        Formatting = Formatting.Indented,
                        ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
                    };

                    string json = JsonConvert.SerializeObject(customDic, settings);

                    File.WriteAllText(saveFile, json);

                    await DispatchToUI(() =>
                    {
                        TitleTextBlock.Text = $"已保存配置: {saveName}";
                        CurrentFileText.Text = $"当前文件: 无";
                        AddLog($"已保存配置: {saveName}", "green");
                        DialogHelper.ShowSuccessMessage(this, $"已保存配置: {saveName}");
                    });

                }
                catch (Exception ex)
                {
                    await DispatchToUI(() =>
                    {
                        TitleTextBlock.Text = "保存为配置失败";
                        CurrentFileText.Text = $"当前文件: 无";
                        AddLog($"保存为配置失败", "red");
                        DialogHelper.ShowErrorMessage(this, $"保存为配置失败: {ex.Message}");
                    });
                }

            }
            else
            {

                await DispatchToUI(() =>
                {
                    AddLog($"正在保存为套装文件", "blue");
                });

                try
                {
                    BKItemWhole wholeItem = new BKItemWhole(saveName);
                    string wholeFolder = wholeItem.BKFolder;
                    string storagePath = LocalStorageHelper.GetBKStoragePath();
                    if (!Directory.Exists(wholeFolder))
                    {
                        Directory.CreateDirectory(wholeFolder);
                    }

                    foreach (var hashPair in customDic)
                    {
                        string path = hashPair.Key;
                        BKItemHash hashItem = hashPair.Value;

                        await DispatchToUI(() =>
                        {
                            AddLog($"正在复制文件: {path}", "blue");
                        });

                        try
                        {
                            string originalFile = hashItem.GetAbsoluteFile(storagePath);
                            string targetFile = Path.Combine(wholeFolder, path);
                            string? targetDirectory = Path.GetDirectoryName(targetFile);
                            if (!string.IsNullOrEmpty(targetDirectory))
                            {
                                Directory.CreateDirectory(targetDirectory);
                            }
                            File.Copy(originalFile, targetFile);

                            await DispatchToUI(() =>
                            {
                                AddLog($"复制文件成功: {path}", "green");
                            });
                        }
                        catch (Exception ex) {
                            await DispatchToUI(() =>
                            {
                                AddLog($"复制文件失败: {ex.Message}", "red");
                            });
                        }

                        await DispatchToUI(() =>
                        {
                            TitleTextBlock.Text = $"已保存套装: {saveName}";
                            CurrentFileText.Text = $"当前文件: 无";
                            AddLog($"已保存套装: {saveName}", "greem");
                            DialogHelper.ShowSuccessMessage(this, $"已保存套装: {saveName}");
                        });
                    }
                }
                catch (Exception ex) {
                    await DispatchToUI(() =>
                    {
                        TitleTextBlock.Text = "保存为套装失败";
                        CurrentFileText.Text = $"当前文件: 无";
                        AddLog($"保存为套装失败", "red");
                        DialogHelper.ShowErrorMessage(this, $"保存为套装失败: {ex.Message}");
                    });
                }
            }
        }

        private Task DispatchToUI(Action uiAction)
        {
            var tcs = new TaskCompletionSource<bool>();
            if (_dispatcherQueue.TryEnqueue(() =>
            {
                try
                {
                    uiAction();
                    tcs.SetResult(true);
                }
                catch (Exception ex)
                {
                    tcs.SetException(ex);
                }
            }))
            {
                return tcs.Task;
            }
            else
            {
                return Task.FromException(new InvalidOperationException("UI 线程已关闭，无法更新进度"));
            }
        }

        private void UpdateProcess(string name, int current, int total)
        {

            CurrentFileText.Text = $"当前文件: {name}";
            FileProgressText.Text = $"处理文件: {current}/{total}";
            FileProgressBar.Value = Math.Round((double)current / total * 100, 1);
        }

        private void AddLog(string content, string color)
        {
            var logItem = new TextBlock
            {
                Text = $"[{DateTime.Now:HH:mm:ss}] {content}",
                Margin = new Thickness(0, 3, 0, 3),
                TextWrapping = TextWrapping.Wrap,
                FontSize = 12,
                Foreground = color.ToLower() switch
                {
                    "red" => new SolidColorBrush(Colors.Red),
                    "green" => new SolidColorBrush(Colors.Green),
                    "blue" => new SolidColorBrush(Colors.Blue),
                    _ => new SolidColorBrush(Colors.Gray),
                }
            };

            LogPanel.Children.Add(logItem);

            LogScrollViewer.ScrollToVerticalOffset(LogScrollViewer.ScrollableHeight);
        }
    }
}
